/*
 * Hyuga: A Density-Grid Stream Clustering Platform.
 * Copyright (C) 2014 PUC-Rio/Laboratory for Advanced Collaboration
 *
 * Hyuga is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * Hyuga is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Hyuga.  If not, see <http://www.gnu.org/licenses/>.
 */
package br.pucrio.inf.lac.konoha.hyuga.listeners;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.apache.log4j.Logger;

import br.pucrio.inf.lac.konoha.hyuga.common.Grid;
import br.pucrio.inf.lac.konoha.hyuga.core.DDSLink;
import br.pucrio.inf.lac.konoha.hyuga.core.HyugaService;
import br.pucrio.inf.lac.konoha.hyuga.events.cell.CellDisperseEvent;
import br.pucrio.inf.lac.konoha.hyuga.events.grid.LockedCellClusterEvent;
import br.pucrio.inf.lac.konoha.hyuga.events.grid.LockedCellDisperseEvent;
import br.pucrio.inf.lac.konoha.hyuga.events.semantics.NewCellClusterEvent;

import com.espertech.esper.client.EPException;

public class GridLockListener {
    
    /** Hyuga. */
    protected HyugaService hyuga;
    
    /** Thread Pool. */
    protected ExecutorService controllerPool;
    
    /** LOGGER. */
    protected static Logger LOGGER = Logger.getLogger(GridLockListener.class.getCanonicalName());
    
    /**
     * Default Constructor.
     * @param ddsLink - DDSLink
     */
    public GridLockListener(HyugaService hyuga) {
        this.hyuga = hyuga;

        controllerPool = Executors.newSingleThreadExecutor();
    }
    
    public enum Mode { WRITE, DELETE };

    public void update(NewCellClusterEvent newCellClusterEvent) {
        controllerPool.submit(new GridModifyThread(newCellClusterEvent, Mode.WRITE));
    }
    
    public void update(CellDisperseEvent cellDisperseEvent) {
        controllerPool.submit(new GridModifyThread(cellDisperseEvent, Mode.DELETE));
    }

    public class GridModifyThread implements Runnable {
        
        Object event;
        Mode mode;
        
        public GridModifyThread(Object event, Mode mode) {
            this.event = event;
            this.mode  = mode;
        }

        @Override
        public void run() {
            try { 
                Grid.gridWriteLock();
                
                switch (mode) {
                    case WRITE:
                        NewCellClusterEvent newCellClusterEvent = (NewCellClusterEvent) event;
                        LockedCellClusterEvent lockedCellClusterEvent = new LockedCellClusterEvent(newCellClusterEvent.getCell());
                        
                        hyuga.getCEPEngine().getEPRuntime().sendEvent(lockedCellClusterEvent);
                        break;
                    case DELETE:
                        CellDisperseEvent cellDisperseEvent = (CellDisperseEvent) event;
                        LockedCellDisperseEvent lockedCellDisperseEvent = new LockedCellDisperseEvent(cellDisperseEvent.getX(), cellDisperseEvent.getY());
                        
                        hyuga.getCEPEngine().getEPRuntime().sendEvent(lockedCellDisperseEvent);
                        break;
                    default:
                        break;
                }
            } catch (EPException ex) {
                LOGGER.error("Exception in GRID Modify Listener: " + ex.getMessage());
            } finally {
                Grid.gridWriteUnlock();
            }
        }
    }
}
